package mapper

import (
	"fmt"
	"gin-demo/models"
	"gin-demo/utils/bizerror"
	"github.com/jinzhu/gorm"
	"reflect"
	"strings"
)

type Mapper interface {
	Insert(model interface{})

	Update(model interface{})

	Delete(model interface{})

	Get(model interface{}) interface{}

	GetByCondition(model interface{}) []interface{}
}

type BaseMapper struct {
}

var db *gorm.DB

func getOrmer() *gorm.DB {
	return db
}

func GetDb() *gorm.DB {
	return db
}

//事物处理
func (baseMapper *BaseMapper) Transaction(invoker func(ormer *gorm.DB)) {
	ormer := getOrmer()
	bizcode.Check(ormer.Begin().Error)

	defer func() {
		if err := recover(); err != nil {
			bizcode.Check(ormer.Rollback().Error)
			panic(err)
		} else {
			bizcode.Check(ormer.Commit().Error)
		}
	}()

	invoker(ormer)
}

func (baseMapper *BaseMapper) Insert(base interface{}) *gorm.DB {
	result := getOrmer().Create(&base)
	bizcode.DbCheck(result.Error)
	return result
}

func (baseMapper *BaseMapper) Update(base interface{}) *gorm.DB {
	result := getOrmer().Updates(base)
	bizcode.DbCheck(result.Error)
	return result
}

func (baseMapper *BaseMapper) Delete(base interface{}) *gorm.DB {
	result := getOrmer().Delete(base)
	bizcode.DbCheck(result.Error)
	return result
}

func (baseMapper *BaseMapper) Get(out interface{}, where interface{}, cols ...interface{}) interface{} {
	bizcode.Check(getOrmer().Where(where).First(&out, cols...).Error)
	return out
}

// where 拼接操作
func (baseMapper *BaseMapper) WhereOp(param interface{}, field string, op string) *models.PageWhereOrder {
	paramType := reflect.TypeOf(param)
	paramValue := reflect.ValueOf(param)
	if paramType.Kind().String() == "string" {
		if paramValue.String() != "" {
			var arr []interface{}
			value := paramValue.String()
			op = strings.ToUpper(op)
			if op == "LIKE" {
				value = "%" + value + "%"
			}
			arr = append(arr, value)
			return &models.PageWhereOrder{Where: fmt.Sprintf("%v %v ?", field, op), Value: arr}
		}
	} else if paramType.Kind().String() == "int" {
		if !paramValue.IsZero() {
			var arr []interface{}
			arr = append(arr, paramValue.Int())
			return &models.PageWhereOrder{Where: fmt.Sprintf("%v %v ?", field, op), Value: arr}
		}
	}
	return nil
}

// 等于
func (baseMapper *BaseMapper) WhereEq(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, "=")
}

// 不等于
func (baseMapper *BaseMapper) WhereNEq(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, "<>")
}

// 大于
func (baseMapper *BaseMapper) WhereGT(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, ">")
}

// 大于等于
func (baseMapper *BaseMapper) WhereEGT(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, ">=")
}

// 小于
func (baseMapper *BaseMapper) WhereLT(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, "<")
}

// 小于等于
func (baseMapper *BaseMapper) WhereELT(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, "<=")
}

// LIKE
func (baseMapper *BaseMapper) WhereLike(param interface{}, field string) *models.PageWhereOrder {
	return baseMapper.WhereOp(param, field, "LIKE")
}

// ORDER排序
func (baseMapper *BaseMapper) WhereOrder(orderKey string) *models.PageWhereOrder {
	if orderKey != "" {
		return &models.PageWhereOrder{Order: orderKey}
	}
	return nil
}
